#include "gamecontrol.h"
#include "playhand.h"

#include<QRandomGenerator>
#include <QTimer>
#include <QDebug>

GameControl::GameControl(QObject *parent) : QObject(parent)
{

}

void GameControl::playerInit()
{
    m_robotLeft = new Robot("机器人1",this);
    m_robotRight = new Robot("机器人2",this);
    m_user = new UserPlayer("玩家",this);

    m_robotLeft->setDirection(Player::Left);
    m_robotRight->setDirection(Player::Right);
    m_user->setDirection(Player::Right);

    Player::Sex sex;
    sex = (Player::Sex)QRandomGenerator::global()->bounded(2);
    m_robotLeft->setSex(sex);
    sex = (Player::Sex)QRandomGenerator::global()->bounded(2);
    m_robotRight->setSex(sex);
    sex = (Player::Sex)QRandomGenerator::global()->bounded(2);
    m_user->setSex(sex);

    m_user->setPrevPlayer(m_robotLeft);
    m_user->setNextPlayer(m_robotRight);

    m_robotLeft->setPrevPlayer(m_robotRight);
    m_robotLeft->setNextPlayer(m_user);

    m_robotRight->setPrevPlayer(m_user);
    m_robotRight->setNextPlayer(m_robotLeft);

    m_curPlayer = m_user;
    connect(m_user,&UserPlayer::notifyGrabLordBet,this,&GameControl::onGrabBet);
    connect(m_robotLeft,&Robot::notifyGrabLordBet,this,&GameControl::onGrabBet);
    connect(m_robotRight,&Robot::notifyGrabLordBet,this,&GameControl::onGrabBet);

    connect(this,&GameControl::pendingInfo,m_robotLeft,&Robot::storePendingInfo);
    connect(this,&GameControl::pendingInfo,m_robotRight,&Robot::storePendingInfo);
    connect(this,&GameControl::pendingInfo,m_user,&UserPlayer::storePendingInfo);

    connect(m_robotLeft,&Robot::notifyPlayHand,this,&GameControl::onPlayHand);
    connect(m_robotRight,&Robot::notifyPlayHand,this,&GameControl::onPlayHand);
    connect(m_user,&UserPlayer::notifyPlayHand,this,&GameControl::onPlayHand);
}

Robot *GameControl::getLeftRobot()
{
    return m_robotLeft;
}

Robot *GameControl::getRightRobot()
{
    return m_robotRight;
}

UserPlayer *GameControl::getUserPlayer()
{
    return m_user;
}

void GameControl::setCurPlayer(Player *player)
{
    m_curPlayer = player;
}

Player *GameControl::getCurPlayer()
{
    return m_curPlayer;
}

Player *GameControl::getPendPlayer()
{
    return m_pendPlayer;
}

Cards GameControl::getPendCards()
{
    return m_pendCard;
}

void GameControl::InitAllCards()
{
    m_allCards.clear();
    for(int i = Card::Card_Begin+1 ; i<Card::Card_SJ;++i)
    {
        for(int j = Card::Suit_Begin+1;j<Card::Suit_End;++j)
        {
            Card card((Card::CardPoint)i,(Card::CardSuit)j);
            m_allCards.add(card);
        }
    }
    m_allCards.add(Card(Card::Card_SJ,Card::Suit_Begin));
    m_allCards.add(Card(Card::Card_BJ,Card::Suit_Begin));
}

Card GameControl::takeOneCard()
{
    return m_allCards.takeRandCard();
}

Cards GameControl::getSurplusCards()
{
    return m_allCards;
}

void GameControl::resetCardsData()
{
    InitAllCards();
    m_robotLeft->clearCards();
    m_robotRight->clearCards();
    m_user->clearCards();
    m_pendPlayer = nullptr;
    m_pendCard.clear();
}

void GameControl::startLandLord()
{
    m_curPlayer->prepareCallLord();
    emit playerStatusChanged(m_curPlayer,ThkingForCallLord);
}

void GameControl::becomeLord(Player *player,int bet)
{
    m_curbet = bet;
    player->setRole(Player::Lord);
    player->getprevPlayer()->setRole(Player::Farmer);
    player->getnextPlayer()->setRole(Player::Farmer);

    m_curPlayer = player;
    player->storeDispatchCard(m_allCards);

    QTimer::singleShot(1000,this,[=](){
        emit gameStatusChanged(PlaingHand);
        emit playerStatusChanged(player,ThkingForPlayHand);
        m_curPlayer->preparePlayHand();
    });

}

void GameControl::clearPlayerScore()
{
    m_robotLeft->setScore(0);
    m_user->setScore(0);
    m_robotRight->setScore(0);
}

void GameControl::onGrabBet(Player *player, int bet)
{
    if(bet == 0 || m_betRecord.bet>=bet)
    {
        emit notifyGrabLordBet(player,0,false);
    }
    else if(bet>0 && m_betRecord.bet == 0)
    {
        emit notifyGrabLordBet(player,bet,true);
    }
    else
    {
        emit notifyGrabLordBet(player,bet,false);
    }

    if(bet == 3)
    {
        becomeLord(player,bet);
        m_betRecord.reset();
        return;
    }
    if(m_betRecord.bet<bet)
    {
        m_betRecord.bet = bet ;
        m_betRecord.player = player;
    }
    m_betRecord.times++;
    if(m_betRecord.times == 3)
    {
        if(m_betRecord.bet == 0)
        {
            emit gameStatusChanged(dispatchCard);
        }
        else
        {
            becomeLord(m_betRecord.player,m_betRecord.bet);
        }
        m_betRecord.reset();
        return;
    }
    m_curPlayer = player->getnextPlayer();
    emit playerStatusChanged(m_curPlayer,ThkingForCallLord);
    m_curPlayer->prepareCallLord();

}

int GameControl::getmaxLordbet()
{
    return m_betRecord.bet;
}

void GameControl::onPlayHand(Player *player, Cards &cards)
{
    emit notifyPlayHand(player,cards);

    if(!cards.isEmpty())
    {
        m_pendCard = cards;
        m_pendPlayer = player;
        emit pendingInfo(player,cards);
    }
    PlayHand::HandType type = PlayHand(cards).getHandType();
    if(type == PlayHand::Hand_Bomb || type == PlayHand::Hand_Bomb_Jokers)
    {
        m_curbet =m_curbet * 2;
    }
    if(player->getCards().isEmpty())
    {
        Player *prev = player->getprevPlayer();
        Player *next = player->getnextPlayer();
        if(player->getRole() == Player::Lord)
        {
            player->setScore(player->getScore()+m_curbet*2);
            prev->setScore(prev->getScore()-m_curbet);
            next->setScore(next->getScore()-m_curbet);
            player->setWin(true);
            prev->setWin(false);
            next->setWin(false);
        }
        else
        {
            player->setWin(true);
            player->setScore(player->getScore()+m_curbet);
            if(prev->getRole() == Player::Lord)
            {
                prev->setScore(prev->getScore()-m_curbet*2);
                next->setScore(next->getScore()+m_curbet);
                prev->setWin(false);
                next->setWin(true);
            }
            else
            {
                next->setScore(next->getScore()-m_curbet*2);
                prev->setScore(prev->getScore()+m_curbet);
                next->setWin(false);
                prev->setWin(true);
            }
        }
        emit playerStatusChanged(player,GameControl::Winning);
        return;
    }
    //m_curPlayer->getnextPlayer();
    m_curPlayer = player->getnextPlayer();
    m_curPlayer->preparePlayHand();
    emit playerStatusChanged(m_curPlayer,GameControl::ThkingForPlayHand);
}

